<template>
  <div
    v-if="editShow"
    id="editor"
    class="editor parent_transform"
    :class="[
      {
        ['edit']: isEdit
      }
    ]"
    :style="editStyle"
    @mousedown="handleMouseDown"
    @scroll="canvasScroll"
  >
    <page-line-editor
      v-if="showPageLine"
      ref="main-page-line"
      :canvas-style-data="canvasStyleData"
    />
    <!-- 网格线 -->
    <Grid
      v-if="showGrid"
      :matrix-style="matrixStyle"
    />
    <PGrid
      v-if="psDebug"
      :position-box="positionBoxInfoArray"
      :matrix-style="matrixStyle"
    />
    <!--页面组件列表展示-->
    <de-drag
      v-for="(item, index) in componentData"
      ref="deDragRef"
      :key="item.id"
      :class="{item:true,moveAnimation:moveAnimate,movingItem:item.isPlayer}"
      :index="index"
      :canvas-id="canvasId"
      :x="getShapeStyleIntDeDrag(item.style,'left')"
      :y="getShapeStyleIntDeDrag(item.style,'top')"
      :w="getShapeStyleIntDeDrag(item.style,'width',item)"
      :h="getShapeStyleIntDeDrag(item.style,'height')"
      :r="item.style.rotate"
      :parent="parentForbid"
      :rotatable="rotatable"
      :default-style="getShapeStyleInt(item.style)"
      :active="item === curComponent"
      :element="item"
      class-name-active="de-drag-active"
      :snap="true"
      :snap-tolerance="2"
      :change-style="customStyle"
      :draggable="deDraggable"
      :resizable="deResizable"
      :linkage-active="linkageActiveCheck(item)"
      :batch-opt-active="batchOptActiveCheck(item)"
      @refLineParams="getRefLineParams"
      @showViewDetails="showViewDetails($event,index)"
      @resizeView="resizeView(index,item)"
      @onResizeStart="startResize"
      @onDragStart="onStartMove"
      @onHandleUp="onMouseUp"
      @onDragging="onDragging"
      @onResizing="onResizing"
      @elementMouseDown="containerMouseDown"
      @amRemoveItem="removeItem(item._dragId)"
      @amAddItem="addItemBox(item)"
      @canvasDragging="canvasDragging"
      @editComponent="editComponent(index,item)"
    >
      <de-out-widget
        v-if="renderOk && item.type==='custom'"
        :id="'component' + item.id"
        ref="wrapperChild"
        :canvas-id="canvasId"
        class="component"
        :style="getComponentStyleDefault(item.style)"
        :prop-value="item.propValue"
        :element="item"
        :is-relation="searchButtonInfo && searchButtonInfo.buttonExist && searchButtonInfo.relationFilterIds.includes(item.id)"
        :out-style="getShapeStyleInt(item.style)"
        :active="item === curComponent"
        :h="getShapeStyleIntDeDrag(item.style,'height')"
        @filter-loaded="filterLoaded"
      />
      <component
        :is="item.component"
        v-else-if="renderOk && item.type==='other'"
        :id="'component' + item.id"
        ref="wrapperChild"
        :canvas-id="canvasId"
        class="component"
        :style="getComponentStyle(item.style)"
        :prop-value="item.propValue"
        :element="item"
        :out-style="getShapeStyleInt(item.style)"
        :active="item === curComponent"
      />
      <component
        :is="item.component"
        v-else-if="renderOk"
        :id="'component' + item.id"
        ref="wrapperChild"
        :canvas-id="canvasId"
        class="component"
        :filters="filterMap[item.propValue && item.propValue.viewId]"
        :style="getComponentStyleDefault(item.style)"
        :prop-value="item.propValue"
        :element="item"
        :out-style="getShapeStyleInt(item.style)"
        :active="item === curComponent"
        :edit-mode="'edit'"
        :h="getShapeStyleIntDeDrag(item.style,'height')"
        :canvas-style-data="canvasStyleData"
        @input="handleInput"
        @trigger-plugin-edit="pluginEditHandler"
        @fill-chart-2-parent="setChartData"
      />
    </de-drag>
    <!--拖拽阴影部分-->
    <drag-shadow
      v-if="shadowShow && dragShadowShow"
      :canvas-id="canvasId"
    />
    <!--切换canvas 拖拽阴影部分-->
    <point-shadow
      v-if="pointShadowShow"
      :canvas-id="canvasId"
    />
    <!-- 右击菜单 -->
    <ContextMenu />

    <!-- 对齐标线 -->
    <span
      v-for="(item, index) in vLine"
      v-show="item.display"
      :key="'v_'+index"
      class="ref-line v-line"
      :style="{
        left: item.position,
        top: item.origin,
        height: item.lineLength,
      }"
    />
    <span
      v-for="(item, index) in hLine"
      :key="'h_'+index"
      class="ref-line h-line"
      :style="{ top: item.position, left: item.origin, width: item.lineLength }"
    />
  </div>
</template>

<script>
import { mapState } from 'vuex'
import Shape from './Shape'
import DeDrag from '@/components/deDrag'

// eslint-disable-next-line no-unused-vars
import { getComponentRotatedStyle, getStyle } from '@/components/canvas/utils/style'
import { _$, imgUrlTrans } from '@/components/canvas/utils/utils'
import ContextMenu from './ContextMenu'
import MarkLine from './MarkLine'
import Area from './Area'
import eventBus from '@/components/canvas/utils/eventBus'
import Grid from './Grid'
import PageLineEditor from './PageLineEditor'
import PGrid from './PGrid'
import { changeStyleWithScale } from '@/components/canvas/utils/translate'
import UserViewDialog from '@/components/canvas/customComponent/UserViewDialog'
import DeOutWidget from '@/components/dataease/DeOutWidget'
import DragShadow from '@/components/deDrag/Shadow'
import bus from '@/utils/bus'
import LinkJumpSet from '@/views/panel/linkJumpSet'
import { buildFilterMap, buildViewKeyMap, formatCondition, valueValid, viewIdMatch, buildAfterFilterLoaded } from '@/utils/conditionUtil'
// 挤占式画布
import _ from 'lodash'
import _jq from 'jquery'
import Background from '@/views/background/index'
import PointShadow from '@/components/deDrag/PointShadow'
import { hexColorToRGBA } from '@/views/chart/chart/util'

// let positionBox = []
// let coordinates = [] // 坐标点集合

let lastTask
let isOverlay = false // 是否正在交换位置
let moveTime = 80 // 移动动画时间

let itemMaxY = 0
let itemMaxX = 0

function debounce(func, time) {
  if (!isOverlay) {
    (function(t) {
      isOverlay = true
      setTimeout(function() {
        t()
        setTimeout(function() {
          isOverlay = false
          if (lastTask !== undefined) {
            debounce(lastTask, time)
          }
        }, moveTime)
      }, time)
    })(func)
    lastTask = undefined
  } else {
    lastTask = func
  }
}

function scrollScreen(e) {
  if (e.clientY + 50 >= window.innerHeight) {
    const body = _jq(document.body)
    body.scrollTop(body.scrollTop() + 20)
  } else if (e.clientY <= 150) {
    const body = _jq(document.body)
    body.scrollTop(body.scrollTop() - 20)
  }
}

/**
 * 重置位置盒子
 *
 */
function resetPositionBox(_this) {
  // 根据当前容器的宽度来决定多少列
  itemMaxX = this.maxCell
  const rows = this.matrixCount.y // 初始100行，后面根据需求会自动增加
  for (let i = 0; i < rows; i++) {
    const row = []
    for (let j = 0; j < this.maxCell; j++) {
      row.push({
        el: false
      })
    }
    this.positionBox.push(row)
  }
}

/**
 * 填充位置盒子
 *
 * @param {any} item
 */
function addItemToPositionBox(item) {
  try {
    const vm = this
    const pb = vm.positionBox
    if (item.x <= 0 || item.y <= 0) return

    for (let i = item.x - 1; i < item.x - 1 + item.sizex; i++) {
      for (let j = item.y - 1; j < item.y - 1 + item.sizey; j++) {
        if (pb[j][i]) {
          pb[j][i].el = item
        }
      }
    }
  } catch (e) {
    // igonre
  }
}

function fillPositionBox(maxY) {
  const vm = this
  const pb = vm.positionBox
  maxY += 1
  for (let j = 0; j < maxY; j++) {
    if (pb[j] === undefined) {
      const row = []
      for (let i = 0; i < itemMaxX; i++) {
        row.push({
          el: false
        })
      }
      pb.push(row)
    }
  }
  itemMaxY = maxY
}

function removeItemFromPositionBox(item) {
  const vm = this
  const pb = vm.positionBox
  if (!item || item.x <= 0 || item.y <= 0) return
  for (let i = item.x - 1; i < item.x - 1 + item.sizex; i++) {
    for (let j = item.y - 1; j < item.y - 1 + item.sizey; j++) {
      if (pb[j][i]) {
        pb[j][i].el = false
      }
    }
  }
}

/**
 * 重新计算宽度，使最小单元格能占满整个容器
 *
 */
function recalcCellWidth() {
  this.maxCell = this.matrixCount.x
}

function init() {
  this.cellWidth = this.baseWidth + this.baseMarginLeft
  this.cellHeight = this.baseHeight + this.baseMarginTop
  this.yourList = this.getList()

  this.positionBox = []
  this.coordinates = [] // 坐标点集合

  lastTask = undefined
  isOverlay = false // 是否正在交换位置
  moveTime = 80 // 移动动画时间

  itemMaxY = 0
  itemMaxX = 0

  const vm = this
  recalcCellWidth.call(this)
  resetPositionBox.call(this)
  initPosition(this)
  let i = 0
  const timeid = setInterval(function() {
    if (i >= vm.yourList.length) {
      clearInterval(timeid)
      vm.$nextTick(function() {
        vm.moveAnimate = true
      })
    } else {
      const item = vm.yourList[i]
      addItem.call(vm, item, i)
      i++
    }
  }, 1)
  vm.renderOk = true
}

function resizePlayer(item, newSize) {
  const vm = this
  removeItemFromPositionBox.call(vm, item)

  const belowItems = findBelowItems.call(this, item)
  _.forEach(belowItems, function(upItem) {
    const canGoUpRows = canItemGoUp.call(vm, upItem)
    if (canGoUpRows > 0) {
      moveItemUp.call(vm, upItem, canGoUpRows)
    }
  })

  item.sizex = newSize.sizex
  item.sizey = newSize.sizey

  // 还原到像素
  item.style.width = item.sizex * this.matrixStyle.originWidth
  item.style.height = item.sizey * this.matrixStyle.originHeight

  if (item.sizex + item.x - 1 > itemMaxX) {
    item.sizex = itemMaxX - item.x + 1
  }

  if (item.sizey + item.y > itemMaxY) {
    fillPositionBox.call(this, item.y + item.sizey)
  }

  emptyTargetCell.call(this, item)
  addItemToPositionBox.call(this, item)
  changeItemCoord.call(this, item)
  const canGoUpRows = canItemGoUp.call(this, item)
  if (canGoUpRows > 0) {
    moveItemUp.call(this, item, canGoUpRows)
  }
}

/**
 * 检查移动的位置，如果不合法，会自动修改
 *
 * @param {any} item
 * @param {any} position
 */
function checkItemPosition(item, position) {
  position = position || {}
  position.x = position.x || item.x
  position.y = position.y || item.y

  // 检查位置
  if (item.x < 1) {
    item.x = 1
  }

  // 检查大小
  if (item.sizex > itemMaxX) {
    item.sizex = itemMaxX
  }

  if (item.sizex < 1) {
    item.sizex = 1
  }

  if (item.x + item.sizex - 1 > itemMaxX) {
    item.x = itemMaxX - item.sizex + 1
    if (item.x < 1) {
      item.x = 1
    }
  }

  if (item.y < 1) {
    item.y = 1
  }

  if (item.sizey < 1) {
    item.sizey = 1
  }

  if (item.y + item.sizey > itemMaxY - 1) {
    fillPositionBox.call(this, item.y + item.sizey - 1)
  }
}

/**
 * 移动正在拖动的元素
 *
 * @param {any} item
 * @param {any} position
 */
function movePlayer(item, position) {
  const vm = this
  removeItemFromPositionBox.call(vm, item)

  const belowItems = findBelowItems.call(this, item)
  _.forEach(belowItems, function(upItem) {
    const canGoUpRows = canItemGoUp.call(vm, upItem)
    if (canGoUpRows > 0) {
      moveItemUp.call(vm, upItem, canGoUpRows)
    }
  })

  item.x = position.x
  item.y = position.y
  checkItemPosition.call(this, item, position)
  emptyTargetCell.call(this, item)
  addItemToPositionBox.call(this, item)
  changeItemCoord.call(this, item)
  const canGoUpRows = canItemGoUp.call(this, item)
  if (canGoUpRows > 0) {
    moveItemUp.call(this, item, canGoUpRows)
  }
}

function removeItem(index) {
  try {
    const vm = this
    const item = this.yourList[index]
    removeItemFromPositionBox.call(vm, item)

    const belowItems = findBelowItems.call(this, item)
    _.forEach(belowItems, function(upItem) {
      const canGoUpRows = canItemGoUp.call(vm, upItem)
      if (canGoUpRows > 0) {
        moveItemUp.call(vm, upItem, canGoUpRows)
      }
    })
    this.yourList.splice(index, 1, {})
    // eslint-disable-next-line
  } catch (e) {
  }
}

// 矩阵设计初始化的时候 预占位，防止编辑仪表板页面，初始化和视图编辑返回时出现组件位置变化问题
function initPosition(_this) {
  _this.yourList.forEach(item => {
    fillPositionBox.call(_this, item.y + item.sizey)
    addItemToPositionBox.call(_this, item)
  })
}

function addItem(item, index) {
  if (index < 0) {
    index = this.yourList.length
  }
  item._dragId = index
  checkItemPosition.call(this, item, {
    x: item.x,
    y: item.y
  })

  emptyTargetCell.call(this, item)
  addItemToPositionBox.call(this, item)
  const canGoUpRows = canItemGoUp.call(this, item)
  if (canGoUpRows > 0) {
    moveItemUp.call(this, item, canGoUpRows)
  }
  // 生成坐标点
  // makeCoordinate.call(this, item);
}

// eslint-disable-next-line no-unused-vars
function changeToCoord(left, top, width, height) {
  return {
    x1: left,
    x2: left + width,
    y1: top,
    y2: top + height,
    c1: left + width / 2,
    c2: top + height / 2
  }
}

/**
 * 检测有无碰撞，并作出处理
 *
 * @param {any} tCoord 比对对象的坐标
 */
// eslint-disable-next-line no-unused-vars
function findClosetCoords(item, tCoord) {
  const vm = this
  if (isOverlay) return
  let i = vm.coordinates.length
  let collisionsItem = []
  while (i--) {
    const nowCoord = vm.coordinates[i]
    if (item._dragId === nowCoord.el._dragId) {
      continue
    }

    if (tCoord.x2 < nowCoord.x1 || tCoord.x1 > nowCoord.x2 || tCoord.y2 < nowCoord.y1 || tCoord.y1 > nowCoord.y2) {
      continue
    } else {
      collisionsItem.push({
        centerDistance: Math.sqrt(Math.pow(tCoord.c1 - nowCoord.c1, 2) + Math.pow(tCoord.c2 - nowCoord.c2, 2)),
        coord: nowCoord
      })
    }
  }

  if (collisionsItem.length <= 0) {
    return
  }

  isOverlay = true

  collisionsItem = _.sortBy(collisionsItem, 'area')

  movePlayer.call(this, item, {
    x: collisionsItem[0].coord.el.x,
    y: collisionsItem[0].coord.el.y
  })

  setTimeout(function() {
    isOverlay = false
  }, 200)
}

/**
 * 生成坐标点
 *
 * @param {any} item
 */
// eslint-disable-next-line no-unused-vars
function makeCoordinate(item) {
  const vm = this
  const width = this.cellWidth * (item.sizex) - this.baseMarginLeft
  const height = this.cellHeight * (item.sizey) - this.baseMarginTop
  const left = this.cellWidth * (item.x - 1) + this.baseMarginLeft
  const top = this.cellHeight * (item.y - 1) + this.baseMarginTop

  const coord = {
    x1: left,
    x2: left + width,
    y1: top,
    y2: top + height,
    c1: left + width / 2,
    c2: top + height / 2,
    el: item
  }

  vm.coordinates.push(coord)
}

function changeItemCoord(item) {
  const vm = this
  const width = this.cellWidth * (item.sizex) - this.baseMarginLeft
  const height = this.cellHeight * (item.sizey) - this.baseMarginTop
  const left = this.cellWidth * (item.x - 1) + this.baseMarginLeft
  const top = this.cellHeight * (item.y - 1) + this.baseMarginTop

  const coord = {
    x1: left,
    x2: left + width,
    y1: top,
    y2: top + height,
    c1: left + width / 2,
    c2: top + height / 2,
    el: item
  }

  const index = _.findIndex(vm.coordinates, function(o) {
    return o.el._dragId === item._dragId
  })
  if (index !== -1) {
    vm.coordinates.splice(index, 1, coord)
  }
}

/**
 * 清空目标位置的元素
 *
 * @param {any} item
 */
function emptyTargetCell(item) {
  const vm = this
  const belowItems = findBelowItems.call(vm, item)

  _.forEach(belowItems, function(downItem, index) {
    if (downItem._dragId === item._dragId) return
    const moveSize = item.y + item.sizey - downItem.y
    if (moveSize > 0) {
      moveItemDown.call(vm, downItem, moveSize)
    }
  })
}

/**
 * 当前位置的item能否上浮
 *
 * @param {any} item
 * @returns
 */
function canItemGoUp(item) {
  const vm = this
  let upperRows = 0
  for (let row = item.y - 2; row >= 0; row--) {
    for (let cell = item.x - 1; cell < item.x - 1 + item.sizex; cell++) {
      if (vm.positionBox[row][cell] && vm.positionBox[row][cell].el) {
        return upperRows
      }
    }
    upperRows++
  }

  return upperRows
}

/**
 * 在移动之前，找到当前下移的元素的下面的元素（递归）
 *
 * @param {any} items
 * @param {any} size
 */
function moveItemDown(item, size) {
  const vm = this
  removeItemFromPositionBox.call(vm, item)
  const belowItems = findBelowItems.call(vm, item)
  _.forEach(belowItems, function(downItem, index) {
    if (downItem._dragId === item._dragId) return
    const moveSize = calcDiff.call(vm, item, downItem, size)
    if (moveSize > 0) {
      moveItemDown.call(vm, downItem, moveSize)
    }
  })
  const targetPosition = {
    y: item.y + size
  }
  setPlayerPosition.call(this, item, targetPosition)
  checkItemPosition.call(this, item, targetPosition)
  addItemToPositionBox.call(this, item)
  changeItemCoord.call(this, item)
}

function setPlayerPosition(item, position) {
  position = position || {}
  const targetX = position.x || item.x
  const targetY = position.y || item.y

  item.x = targetX
  item.y = targetY

  // 还原到像素
  item.style.left = (item.x - 1) / this.matrixScaleWidth
  item.style.top = (item.y - 1) / this.matrixScaleHeight
  if (item.y + item.sizey > itemMaxY) {
    itemMaxY = item.y + item.sizey
  }
}

/**
 * 寻找子元素到父元素的最大距离
 *
 * @param {any} parent
 * @param {any} son
 * @param {any} size
 */
function calcDiff(parent, son, size) {
  const diffs = []
  const vm = this
  for (let i = son.x - 1; i < son.x - 1 + son.sizex; i++) {
    let temp_y = 0

    for (let j = parent.y - 1 + parent.sizey; j < son.y - 1; j++) {
      if (vm.positionBox[j][i] && vm.positionBox[j][i].el === false) {
        temp_y++
      }
    }
    diffs.push(temp_y)
  }

  const max_diff = Math.max.apply(Math, diffs)
  size = size - max_diff

  return size > 0 ? size : 0
}

function moveItemUp(item, size) {
  const vm = this

  removeItemFromPositionBox.call(vm, item)

  const belowItems = findBelowItems.call(this, item)
  setPlayerPosition.call(this, item, {
    y: item.y - size
  })

  addItemToPositionBox.call(this, item)

  changeItemCoord.call(this, item)

  _.forEach(belowItems, function(upItem, index) {
    const moveSize = canItemGoUp.call(vm, upItem)
    if (moveSize > 0) {
      moveItemUp.call(vm, upItem, moveSize)
    }
  })
}

function findBelowItems(item) {
  const belowItems = {}
  const vm = this
  for (let cell = item.x - 1; cell < item.x - 1 + item.sizex; cell++) {
    for (let row = item.y - 1; row < vm.positionBox.length; row++) {
      try {
        const target = vm.positionBox[row][cell]
        if (target && target.el) {
          belowItems[target.el._dragId] = target.el
          break
        }
      } catch (e) {
        console.error('positionBox igonre', e)
      }
    }
  }

  return _.sortBy(_.values(belowItems), 'y')
}

// eslint-disable-next-line no-unused-vars
function getoPsitionBox() {
  return this.positionBox
}

export default {
  components: {
    PointShadow,
    Background,
    Shape,
    ContextMenu,
    MarkLine,
    // eslint-disable-next-line
    Area,
    Grid,
    PGrid,
    DeDrag,
    UserViewDialog,
    DeOutWidget,
    DragShadow,
    LinkJumpSet,
    PageLineEditor
  },
  props: {
    parentForbid: {
      type: Boolean,
      require: false,
      default: true
    },
    canvasStyleData: {
      type: Object,
      require: true
    },
    componentData: {
      type: Array,
      require: false,
      default: () => []
    },
    canvasId: {
      type: String,
      require: true
    },
    isEdit: {
      type: Boolean,
      require: false,
      default: true
    },
    outStyle: {
      type: Object,
      require: false,
      default: null
    },
    // 挤占式画布设计
    dragStart: {
      required: false,
      type: Function,
      default: function() {
      }
    },
    dragging: {
      required: false,
      type: Function,
      default: function() {
      }
    },
    dragEnd: {
      required: false,
      type: Function,
      default: function() {
      }
    },
    resizable: {
      required: false,
      type: Boolean,
      default: true
    },
    resizeStart: {
      required: false,
      type: Function,
      default: function() {
      }
    },
    resizing: {
      required: false,
      type: Function,
      default: function() {
      }
    },
    resizeEnd: {
      required: false,
      type: Function,
      default: function() {
      }
    },
    matrixCount: {
      required: true,
      type: Object
    },
    scrollTop: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      dragShadowShow: true,
      psDebug: false, // 定位调试模式
      editorX: 0,
      editorY: 0,
      start: { // 选中区域的起点
        x: 0,
        y: 0
      },
      width: 0,
      height: 0,
      isShowArea: false,
      conditions: [],

      // 初始化 设置放大比例为3倍 防止在边框限制时 出现较小的父级支持造成组件位移
      scaleWidth: 100,
      scaleHeight: 100,
      // 放大比例 小数
      scalePointWidth: 1,
      scalePointHeight: 1,

      timer: null,
      // private 是否可旋转
      rotatable: false,
      // 矩阵大小
      matrixStyle: {
        width: 80, // 当前尺寸
        height: 20,
        originWidth: 80, // 原始尺寸
        originHeight: 20
      },
      filterMapCache: {},
      showDrag: true,
      vLine: [],
      hLine: [],
      changeIndex: 0,
      timeMachine: null,
      // 挤占式画布设计
      baseWidth: 100,
      baseHeight: 100,
      baseMarginLeft: 0,
      baseMarginTop: 0,
      draggable: true,
      renderOk: false,
      moveAnimate: false,
      list: [],
      cellWidth: 100,
      cellHeight: 100,
      maxCell: 0,
      lastComponentDataLength: 0,
      positionBoxInfoArray: [],
      positionBox: [],
      coordinates: [],
      yourList: [],
      infoBox: null,
      editShow: false,
      buttonFilterMap: null,
      autoTrigger: true
    }
  },
  computed: {
    matrixScaleWidth() {
      return this.scalePointWidth / this.matrixStyle.width
    },
    matrixScaleHeight() {
      return this.scalePointHeight / this.matrixStyle.height
    },
    moveTabCollisionActive() {
      return this.tabCollisionActiveId
    },
    pointShadowShow() {
      return this.canvasId === 'canvas-main' &&
        this.curComponent &&
        this.curComponent.canvasId !== 'canvas-main' &&
        this.tabMoveOutComponentId
    },
    shadowShow() {
      return ((this.curComponent &&
          this.curComponent.auxiliaryMatrix &&
          this.curComponent.canvasId === this.canvasId &&
          (this.curComponent.optStatus.dragging || this.curComponent.optStatus.resizing)) ||
        (this.dragComponentInfo && this.dragComponentInfo.canvasId === this.canvasId)) && !this.tabMoveInActive
    },
    tabMoveInActive() {
      return this.tabMoveInActiveId
    },
    deDraggable() {
      return !this.linkageSettingStatus && !this.batchOptStatus
    },
    deResizable() {
      return !this.linkageSettingStatus && !this.batchOptStatus
    },
    showGrid() {
      if (this.canvasStyleData && this.canvasStyleData.aidedDesign && this.canvasId === 'canvas-main') {
        return this.canvasStyleData.aidedDesign.showGrid
      } else {
        return false
      }
    },
    showPageLine() {
      if (this.canvasStyleData && this.canvasStyleData.pdfPageLine) {
        return this.canvasStyleData.pdfPageLine.showPageLine
      }
      return false
    },
    editStyle() {
      return {
        height: this.outStyle.height + this.scrollTop + 'px !important'
      }
    },
    scrollHeight() {
      let baseHeight = 0
      this.componentData.forEach(item => {
        const top = this.getShapeStyleIntDeDrag(item.style, 'top')
        const height = this.getShapeStyleIntDeDrag(item.style, 'height')
        baseHeight = Math.max(baseHeight, top + height)
      })
      return baseHeight
    },
    customStyle() {
      let style = {
        width: '100%',
        height: '100%'
      }

      if (this.canvasStyleData.openCommonStyle) {
        if (this.canvasStyleData.panel.backgroundType === 'image' && this.canvasStyleData.panel.imageUrl) {
          style = {
            background: `url(${imgUrlTrans(this.canvasStyleData.panel.imageUrl)}) no-repeat`,
            ...style
          }
        } else if (this.canvasStyleData.panel.backgroundType === 'color') {
          const colorRGBA = hexColorToRGBA(this.canvasStyleData.panel.color, this.canvasStyleData.panel.alpha === undefined ? 100 : this.canvasStyleData.panel.alpha)
          style = {
            background: colorRGBA,
            ...style
          }
        }
      }
      return style
    },
    panelInfo() {
      return this.$store.state.panel.panelInfo
    },
    dragComponentInfo() {
      return this.$store.state.dragComponentInfo
    },
    curCanvasScaleSelf() {
      return this.curCanvasScaleMap[this.canvasId]
    },
    ...mapState([
      'canvasStyleData',
      'curComponent',
      'editor',
      'linkageSettingStatus',
      'curLinkageView',
      'doSnapshotIndex',
      'componentGap',
      'mobileLayoutStatus',
      'curCanvasScaleMap',
      'batchOptStatus',
      'tabMoveInActiveId',
      'tabCollisionActiveId',
      'tabMoveOutComponentId'
    ]),

    searchButtonInfo() {
      const result = this.buildButtonFilterMap(this.$store.state.componentData)
      return result
    },
    filterMap() {
      const result = buildFilterMap(this.componentData)
      Object.keys(result).forEach(ele => {
        if (this.filterMapCache[ele]?.length) {
          result[ele].forEach(itx => {
            const condition = this.filterMapCache[ele].find(item => item.componentId === itx.componentId && itx.cacheObj)
            if (condition) {
              itx.cacheObj = condition.cacheObj
            }
          })
        } else {
          this.filterMapCache[ele] = result[ele]
        }
      })
      if (this.searchButtonInfo && this.searchButtonInfo.buttonExist && !this.searchButtonInfo.autoTrigger && this.searchButtonInfo.relationFilterIds) {
        for (const key in result) {
          if (Object.hasOwnProperty.call(result, key)) {
            let filters = result[key]
            filters = filters.filter(item => !this.searchButtonInfo.relationFilterIds.includes(item.componentId))
            result[key] = filters
          }
        }
      }
      return result
    }

  },
  watch: {
    'curComponent.id': {
      handler(newVal) {
        // curComponent.id 变动刷新dragShadow组件 防止出现连续的阴影动画移动
        this.dragShadowShow = false
        this.$nextTick(() => {
          this.dragShadowShow = true
        })
      },
      deep: true
    },
    scrollHeight: {
      handler(newVal, oldVla) {
        this.$nextTick(() => {
          if (newVal !== oldVla && this.showPageLine) {
            const lineRef = this.$refs['main-page-line']
            if (lineRef?.init) {
              lineRef.init(newVal)
            }
          }
        })
      },
      deep: true
    },
    outStyle: {
      handler(newVal, oldVla) {
        this.resizeParentBoundsRef()
        this.changeScale()
      },
      deep: true
    },
    componentData: {
      handler(newVal, oldVla) {
        // 初始化时componentData 加载可能出现慢的情况 此时重新初始化一下matrix
        if (newVal.length !== this.lastComponentDataLength) {
          this.lastComponentDataLength = newVal.length
          this.initMatrix()
        }
      },
      deep: true
    },
    // 镜像索引有变化 刷新一下矩阵（撤销重做等）
    doSnapshotIndex: {
      handler(newVal, oldVla) {
        this.initMatrix()
      },
      deep: true
    },
    autoTrigger: {
      handler(val, old) {
        if (val === old) return
        const result = buildFilterMap(this.componentData)
        for (const key in result) {
          if (Object.hasOwnProperty.call(result, key)) {
            let filters = result[key]
            if (this.searchButtonInfo && this.searchButtonInfo.buttonExist && !this.searchButtonInfo.autoTrigger && this.searchButtonInfo.relationFilterIds) {
              filters = filters.filter(item => !this.searchButtonInfo.relationFilterIds.includes(item.componentId))
            }

            this.filterMap[key] = filters

            this.componentData.forEach(item => {
              if (item.type === 'view' && item.propValue.viewId === key) {
                item.filters = filters
              }
            })
          }
        }
      },
      deep: true
    }
  },

  mounted() {
    this.canvasInit()
    // 获取编辑器元素
    this.$store.commit('getEditor')
    const _this = this
    eventBus.$on('hideArea', this.hideArea)
    eventBus.$on('componentSizeAdaptorChange', this.changeScale)
    eventBus.$on('startMoveIn', this.startMoveIn)
    bus.$on('onRemoveLastItem', this.removeLastItem)
    bus.$on('trigger-search-button', this.triggerSearchButton)
    bus.$on('trigger-reset-button', this.triggerResetButton)
    bus.$on('refresh-button-info', this.refreshButtonInfo)

    // 矩阵定位调试模式
    if (this.psDebug) {
      setInterval(() => {
        _this.positionBoxInfoArray = _this.positionBox
      }, 500)
    }
  },
  beforeDestroy() {
    eventBus.$off('hideArea', this.hideArea)
    eventBus.$off('startMoveIn', this.startMoveIn)
    eventBus.$off('componentSizeAdaptorChange', this.changeScale)
    bus.$off('onRemoveLastItem', this.removeLastItem)
    bus.$off('trigger-search-button', this.triggerSearchButton)
    bus.$off('refresh-button-info', this.refreshButtonInfo)
    bus.$off('trigger-reset-button', this.triggerResetButton)
  },
  methods: {
    filterLoaded(p) {
      buildAfterFilterLoaded(this.filterMap, p)
      this.filterMapCache = {}
    },
    getWrapperChildRefs() {
      return this.$refs['wrapperChild']
    },
    getAllWrapperChildRefs() {
      const allChildRefs = []
      const currentChildRefs = this.getWrapperChildRefs()
      if (currentChildRefs && currentChildRefs.length > 0) {
        allChildRefs.push.apply(allChildRefs, currentChildRefs)
      }
      currentChildRefs && currentChildRefs.forEach(subRef => {
        if (subRef?.getType && subRef.getType() === 'de-tabs') {
          const currentTabChildRefs = subRef.getWrapperChildRefs()
          if (currentTabChildRefs && currentTabChildRefs.length > 0) {
            allChildRefs.push.apply(allChildRefs, currentTabChildRefs)
          }
        }
      })
      return allChildRefs
    },
    setChartData(chart) {
      this.componentData.forEach((item, index) => {
        if (item.type === 'view' && item.component === 'user-view' && item.propValue.viewId === chart.id) {
          this.$refs['deDragRef'][index].setChartData(chart)
        }
      })
    },
    triggerResetButton() {
      this.triggerSearchButton(true)
      this.$refs['wrapperChild']?.forEach(item => {
        if (item?.['responseResetButton']) {
          item.responseResetButton()
        }
      })
    },
    refreshButtonInfo(isClear = false) {
      const result = this.buildButtonFilterMap(this.$store.state.componentData, isClear)
      this.searchButtonInfo.buttonExist = result.buttonExist
      this.searchButtonInfo.relationFilterIds = result.relationFilterIds
      this.searchButtonInfo.filterMap = result.filterMap
      this.searchButtonInfo.autoTrigger = result.autoTrigger
      this.buttonFilterMap = this.searchButtonInfo.filterMap
    },
    triggerSearchButton(isClear = false) {
      if (this.canvasId !== 'canvas-main') {
        return
      }
      this.refreshButtonInfo(isClear)
      this.buttonFilterMap = this.searchButtonInfo.filterMap
      this.$store.state.componentData.forEach(component => {
        if (component.type === 'view' && this.buttonFilterMap[component.propValue.viewId]) {
          component.filters = this.buttonFilterMap[component.propValue.viewId]
        }
        if (component.type === 'de-tabs') {
          for (let idx = 0; idx < component.options.tabList.length; idx++) {
            const ele = component.options.tabList[idx].content
            if (!ele.type || ele.type !== 'view') continue
            ele.filters = this.buttonFilterMap[ele.propValue.viewId]
          }
        }
      })
    },
    buildButtonFilterMap(panelItems, isClear = false) {
      const result = {
        buttonExist: false,
        relationFilterIds: [],
        autoTrigger: true,
        filterMap: {}
      }
      if (!panelItems || !panelItems.length) return result
      let sureButtonItem = null
      result.buttonExist = panelItems.some(item => {
        if (item.type === 'custom-button' && item.serviceName === 'buttonSureWidget') {
          sureButtonItem = item
          return true
        }
      })

      if (!result.buttonExist) return result

      const customRange = sureButtonItem.options.attrs.customRange
      result.autoTrigger = sureButtonItem.options.attrs.autoTrigger
      this.autoTrigger = result.autoTrigger

      const allFilters = panelItems.filter(item => item.type === 'custom')

      const matchFilters = customRange && allFilters.filter(item => sureButtonItem.options.attrs.filterIds.includes(item.id)) || allFilters

      result.relationFilterIds = matchFilters.map(item => item.id)

      let viewKeyMap = buildViewKeyMap(panelItems)
      viewKeyMap = this.buildViewKeyFilters(matchFilters, viewKeyMap, isClear)
      result.filterMap = viewKeyMap
      return result
    },
    buildViewKeyFilters(panelItems, result, isClear = false) {
      const wrapperChildAll = this.getAllWrapperChildRefs()
      if (!wrapperChildAll || !wrapperChildAll.length) return result
      panelItems.forEach((element) => {
        let param = null
        let wrapperChild
        wrapperChildAll?.forEach(item => {
          if (item?.['getComponentId'] && item.getComponentId() === element.id) {
            wrapperChild = item
          }
        })
        if (!wrapperChild || !wrapperChild.getCondition) return true
        if (isClear) {
          wrapperChild.clearHandler && wrapperChild.clearHandler()
        }
        param = wrapperChild.getCondition && wrapperChild.getCondition()
        const condition = formatCondition(param)
        let vValid = valueValid(condition)
        const required = element.options.attrs.required
        condition.requiredInvalid = required && !vValid
        vValid = vValid || required
        const filterComponentId = condition.componentId
        const conditionCanvasId = wrapperChild.getCanvasId && wrapperChild.getCanvasId()
        Object.keys(result).forEach(viewId => {
          const vidMatch = viewIdMatch(condition.viewIds, viewId)
          const viewFilters = result[viewId]
          const canvasMatch = this.checkCanvasViewIdsMatch(conditionCanvasId, viewId)
          let j = viewFilters.length
          while (j--) {
            const filter = viewFilters[j]
            if (filter.componentId === filterComponentId) {
              viewFilters.splice(j, 1)
            }
          }
          canvasMatch && vidMatch && vValid && viewFilters.push(condition)
        })
      })
      return result
    },
    checkCanvasViewIdsMatch(conditionCanvasId, viewId) {
      if (conditionCanvasId === 'canvas-main') {
        return true
      }
      for (let index = 0; index < this.$store.state.componentData.length; index++) {
        const item = this.$store.state.componentData[index]
        if (item.type === 'view' && item.propValue.viewId === viewId && item.canvasId === conditionCanvasId) return true
      }
      return false
    },
    getComponentIndex(id) {
      for (let index = 0; index < this.$store.state.componentData.length; index++) {
        const item = this.$store.state.componentData[index]
        if (item.id === id) return index
      }
      return -1
    },
    pluginEditHandler({ e, id }) {
      let index = -1
      for (let i = 0; i < this.componentData.length; i++) {
        const item = this.componentData[i]
        const itemId = item.id
        if (id === itemId) {
          index = i
          break
        }
      }
      if (index >= 0) {
        const _this = this
        _this.$refs.deDragRef && _this.$refs.deDragRef[index] && _this.$refs.deDragRef[index].triggerPluginEdit && _this.$refs.deDragRef[index].triggerPluginEdit(e)
      }
    },
    linkageActiveCheck(item) {
      return this.linkageSettingStatus && item === this.curLinkageView
    },
    batchOptActiveCheck(item) {
      return this.batchOptStatus && item.type === 'view'
    },
    canvasInit() {
      this.editShow = false
      setTimeout(() => {
        this.changeScale()
        this.editShow = true
      }, 500)
    },
    changeStyleWithScale,
    handleMouseDown(e) {
      if (this.isPageLineTarget(e)) {
        return
      }
      // 如果没有选中组件 在画布上点击时需要调用 e.preventDefault() 防止触发 drop 事件
      if (!this.curComponent || (this.curComponent.component !== 'v-text' && this.curComponent.component !== 'rect-shape')) {
        e.preventDefault()
      }
      this.hideArea()
      // 挤占式画布设计
      this.containerMouseDown(e)
    },
    isPageLineTarget(e) {
      return e.target.classList && [...e.target.classList].includes('page-line-item')
    },

    hideArea() {
      this.isShowArea = 0
      this.width = 0
      this.height = 0
    },

    createGroup() {
      // 获取选中区域的组件数据
      const areaData = this.getSelectArea()
      if (areaData.length <= 1) {
        this.hideArea()
        return
      }

      // 根据选中区域和区域中每个组件的位移信息来创建 Group 组件
      // 要遍历选择区域的每个组件，获取它们的 left top right bottom 信息来进行比较
      let top = Infinity
      let left = Infinity
      let right = -Infinity
      let bottom = -Infinity
      areaData.forEach(component => {
        let style = {}
        if (component.component === 'Group') {
          component.propValue.forEach(item => {
            const rectInfo = _$(`#component${item.id}`).getBoundingClientRect()
            style.left = rectInfo.left - this.editorX
            style.top = rectInfo.top - this.editorY
            style.right = rectInfo.right - this.editorX
            style.bottom = rectInfo.bottom - this.editorY

            if (style.left < left) left = style.left
            if (style.top < top) top = style.top
            if (style.right > right) right = style.right
            if (style.bottom > bottom) bottom = style.bottom
          })
        } else {
          style = getComponentRotatedStyle(component.style)
        }

        if (style.left < left) left = style.left
        if (style.top < top) top = style.top
        if (style.right > right) right = style.right
        if (style.bottom > bottom) bottom = style.bottom
      })

      this.start.x = left
      this.start.y = top
      this.width = right - left
      this.height = bottom - top

      // 设置选中区域位移大小信息和区域内的组件数据
      this.$store.commit('setAreaData', {
        style: {
          left,
          top,
          width: this.width,
          height: this.height
        },
        components: areaData
      })
    },

    getSelectArea() {
      const result = []
      // 区域起点坐标
      const { x, y } = this.start
      // 计算所有的组件数据，判断是否在选中区域内
      this.componentData.forEach(component => {
        if (component.isLock) return

        const { left, top, width, height } = component.style
        if (x <= left && y <= top && (left + width <= x + this.width) && (top + height <= y + this.height)) {
          result.push(component)
        }
      })

      // 返回在选中区域内的所有组件
      return result
    },

    getShapeStyle(style) {
      const result = {};
      ['width', 'left'].forEach(attr => {
        result[attr] = this.format(style[attr], this.scaleWidth) + 'px'
      });
      ['height', 'top'].forEach(attr => {
        result[attr] = this.format(style[attr], this.scaleHeight) + 'px'
      })
      result.transform = 'rotate(' + style['rotate'] + 'deg)'

      return result
    },

    getShapeStyleInt(style) {
      const result = {};
      ['width', 'left'].forEach(attr => {
        result[attr] = this.format(style[attr], this.scaleWidth)
      });
      ['height', 'top'].forEach(attr => {
        result[attr] = this.format(style[attr], this.scaleHeight)
      })
      result['rotate'] = style['rotate']
      result['borderWidth'] = style['borderWidth']
      result['opacity'] = style['opacity']

      return result
    },

    getComponentStyleDefault(style) {
      return getStyle(style, ['top', 'left', 'width', 'height', 'rotate'])
      // return style
    },

    getComponentStyle(style) {
      //   return getStyle(style, ['top', 'left', 'width', 'height', 'rotate'])
      return style
    },

    handleInput(element, value) {
      // 根据文本组件高度调整 shape 高度
      // remain -自适应画布会导致一些问题 暂时不修改
      // this.$store.commit('setShapeStyle', { height: this.getTextareaHeight(element, value) })
    },

    getTextareaHeight(element, text) {
      // eslint-disable-next-line prefer-const
      let { lineHeight, fontSize, height } = element.style
      if (lineHeight === '') {
        lineHeight = 1.5
      }

      const newHeight = (text.split('<br>').length - 1) * lineHeight * fontSize
      return height > newHeight ? height : newHeight
    },

    format(value, scale) {
      // 自适应画布区域 返回原值
      return value * scale / 100
    },
    // 修改矩阵点
    changeComponentSizePoint(pointScale) {
      if (pointScale) {
        this.componentData.forEach((item, index) => {
          item.x = (item.x - 1) * pointScale + 1
          item.y = (item.y - 1) * pointScale + 1
          item.sizex = item.sizex * pointScale
          item.sizey = item.sizey * pointScale
        })
        this.changeScale()
      }
    },

    changeScale() {
      // 1.3 版本重新设计仪表板定位方式，基准画布宽高为 1600*900 宽度自适应当前画布获取缩放比例scaleWidth
      // 高度缩放比例scaleHeight = scaleWidth 基础矩阵为128*72 矩阵原始宽度12.5*12.5 矩阵高度可以调整

      if (this.outStyle.width && this.outStyle.height) {
        // 矩阵计算
        this.matrixStyle.originWidth = this.canvasStyleData.width / this.matrixCount.x
        this.matrixStyle.originHeight = this.canvasStyleData.height / this.matrixCount.y
        if (!this.canvasStyleData.selfAdaption) {
          this.matrixStyle.width = this.canvasStyleData.width / this.matrixCount.x
          this.matrixStyle.height = this.canvasStyleData.height / this.matrixCount.y
        } else {
          this.matrixStyle.width = this.outStyle.width / this.matrixCount.x
          this.matrixStyle.height = this.outStyle.height / this.matrixCount.y
        }
        this.baseWidth = this.matrixStyle.width
        this.baseHeight = this.matrixStyle.height
        this.cellWidth = this.matrixStyle.width
        this.cellHeight = this.matrixStyle.height
        this.initMatrix()

        this.scaleWidth = this.outStyle.width * 100 / this.canvasStyleData.width
        this.scaleHeight = this.outStyle.height * 100 / this.canvasStyleData.height
        this.scalePointWidth = this.scaleWidth / 100
        this.scalePointHeight = this.scaleHeight / 100
        this.$store.commit('setCurCanvasScale',
          {
            canvasId: this.canvasId,
            scaleWidth: this.scaleWidth,
            scaleHeight: this.scaleHeight,
            scalePointWidth: this.scalePointWidth,
            scalePointHeight: this.scalePointHeight,
            matrixStyleWidth: this.matrixStyle.width,
            matrixStyleHeight: this.matrixStyle.height,
            matrixStyleOriginWidth: this.matrixStyle.originWidth,
            matrixStyleOriginHeight: this.matrixStyle.originHeight
          })
        if (this.canvasId === 'canvas-main') {
          this.$store.commit('setPreviewCanvasScale', {
            scaleWidth: this.canvasStyleData.autoSizeAdaptor ? this.scalePointWidth : 1,
            scaleHeight: this.canvasStyleData.autoSizeAdaptor ? this.scalePointHeight : 1
          })
        }
      }
    },
    getShapeStyleIntDeDrag(style, prop, item) {
      if (prop === 'rotate') {
        return style['rotate']
      }
      if (prop === 'width') {
        const result = this.format(style['width'], this.scaleWidth)
        return result
      }
      if (prop === 'left') {
        return this.format(style['left'], this.scaleWidth)
      }
      if (prop === 'height') {
        return this.format(style['height'], this.scaleHeight)
      }
      if (prop === 'top') {
        const top = this.format(style['top'], this.scaleHeight)
        return top
      }
    },
    getRefLineParams(params) {
      const { vLine, hLine } = params
      this.vLine = vLine
      this.hLine = hLine
    },
    resizeParentBounds() {
      this.destroyTimeMachine()
      this.changeIndex++
      this.parentBoundsChange(this.changeIndex)
    },
    parentBoundsChange(index) {
      this.timeMachine = setTimeout(() => {
        if (index === this.changeIndex) {
          this.changeScale()
        }
        this.destroyTimeMachine()
      }, 1500)
    },
    destroyTimeMachine() {
      this.timeMachine && clearTimeout(this.timeMachine)
      this.timeMachine = null
    },
    showViewDetails(params, index) {
      this.$refs.wrapperChild[index].openChartDetailsDialog(params)
    },

    resizeView(index, item) {
      if (item.type === 'view' || item.type === 'de-show-date') {
        try {
          this.$refs.wrapperChild[index].chartResize()
        } catch (e) {
          // ignore error
        }
      }
    },
    editComponent(index, item) {
      if (item.type === 'view') {
        this.$refs.wrapperChild[index].editChart()
      }
    },
    handleDragOver(e) {
      if (!this.dragComponentInfo?.shadowStyle) {
        return
      }
      this.dragComponentInfo.shadowStyle.x = e.pageX - 220
      this.dragComponentInfo.shadowStyle.y = e.pageY - 90 + this.scrollTop
      this.dragComponentInfo.style.left = this.dragComponentInfo.shadowStyle.x / this.scalePointWidth
      this.dragComponentInfo.style.top = this.dragComponentInfo.shadowStyle.y / this.scalePointHeight
      if (this.dragComponentInfo.auxiliaryMatrix) {
        this.onDragging(e, this.dragComponentInfo)
      }
    },
    getPositionX(x) {
      if (this.canvasStyleData.selfAdaption) {
        return x * 100 / this.curCanvasScale.scaleWidth
      } else {
        return x
      }
    },
    getPositionY(y) {
      if (this.canvasStyleData.selfAdaption) {
        return y * 100 / this.curCanvasScale.scaleHeight
      } else {
        return y
      }
    },
    canvasScroll(event) {
      this.$emit('canvasScroll', event)
    },

    // 挤占式画布设计
    startResize(e, item, index) {
      if (!this.resizable) return
      this.resizeStart.call(null, e, item, index)

      // e.preventDefault();
      // eslint-disable-next-line no-unused-vars
      const target = _jq(e.target)

      if (!this.infoBox) {
        this.infoBox = {}
      }
      this.infoBox.resizeItem = item
      this.infoBox.resizeItemIndex = index
      // this.onStartMove(e, item, index)

      return true
    },
    containerMouseDown(e) {
      // e.preventDefault();
      if (!this.infoBox) {
        this.infoBox = {}
      }
      this.infoBox.startX = e.pageX
      this.infoBox.startY = e.pageY
    },
    onStartMove(e, item, index) {
      if (!this.infoBox) {
        this.infoBox = {}
      }
      const infoBox = this.infoBox
      this.dragStart.call(null, e, item, index)
      infoBox.moveItem = item
      infoBox.moveItemIndex = index

      infoBox.originX = 0 // 克隆对象原始X位置
      infoBox.originY = 0
      infoBox.startX = 0
      infoBox.startY = 0

      infoBox.oldX = item.x // 实际对象原始X位置
      infoBox.oldY = item.y
      infoBox.oldSizeX = item.sizex
      infoBox.oldSizeY = item.sizey
    },
    onMouseUp(e) {
      const vm = this
      if (_.isEmpty(vm.infoBox)) return
      if (vm.infoBox.cloneItem) {
        vm.infoBox.cloneItem.remove()
      }
      if (vm.infoBox.resizeItem) {
        vm.$delete(vm.infoBox.resizeItem, 'isPlayer')
        vm.resizeEnd.call(null, e, vm.infoBox.resizeItem, vm.infoBox.resizeItem._dragId)
      }
      if (vm.infoBox.moveItem) {
        vm.dragEnd.call(null, e, vm.infoBox.moveItem, vm.infoBox.moveItem._dragId)
        vm.$set(vm.infoBox.moveItem, 'show', true)
        vm.$delete(vm.infoBox.moveItem, 'isPlayer')
      }
      vm.infoBox = {}
    },
    onResizing(e, item) {
      // this.onDragging(e, item)
      const infoBox = this.infoBox
      const resizeItem = _.get(infoBox, 'resizeItem')
      const vm = this
      vm.$set(resizeItem, 'isPlayer', true)
      let nowX = Math.round(item.style.width * this.matrixScaleWidth)
      let nowY = Math.round(item.style.height * this.matrixScaleHeight)
      nowX = nowX > 0 ? nowX : 1
      nowY = nowY > 0 ? nowY : 1

      const oldX = infoBox.oldX
      const oldY = infoBox.oldY
      let newX = Math.round(item.style.left * this.matrixScaleWidth) + 1
      let newY = Math.round(item.style.top * this.matrixScaleHeight) + 1
      newX = newX > 0 ? newX : 1
      newY = newY > 0 ? newY : 1
      if (item.sizex !== nowX || item.sizey !== nowY) {
        debounce((function(newX, oldX, newY, oldY) {
          return function() {
            if (newX !== oldX || oldY !== newY) {
              movePlayer.call(vm, resizeItem, {
                x: newX,
                y: newY
              })
              infoBox.oldX = newX
              infoBox.oldY = newY
            }
            resizePlayer.call(vm, resizeItem, {
              sizex: nowX,
              sizey: nowY
            })
          }
        })(newX, oldX, newY, oldY), 10)
      }
    },
    onDragging(e, item) {
      const infoBox = this.infoBox
      const moveItem = _.get(infoBox, 'moveItem')
      const vm = this
      scrollScreen(e)
      if (!vm.draggable) return
      vm.dragging.call(null, e, moveItem, moveItem._dragId)

      vm.$set(moveItem, 'isPlayer', true)
      const oldX = infoBox.oldX
      const oldY = infoBox.oldY
      let newX = Math.round((item.style.left * this.scalePointWidth) / this.matrixStyle.width) + 1
      let newY = Math.round((item.style.top * this.scalePointHeight) / this.matrixStyle.height) + 1
      newX = newX > 0 ? newX : 1
      newY = newY > 0 ? newY : 1
      if (this.moveTabCollisionActive) {
        return
      }
      if (newX !== oldX || oldY !== newY) {
        debounce((function(newX, oldX, newY, oldY) {
          return function() {
            if (newX !== oldX || oldY !== newY) {
              movePlayer.call(vm, moveItem, {
                x: newX,
                y: newY
              })

              infoBox.oldX = newX
              infoBox.oldY = newY
            }
          }
        })(newX, oldX, newY, oldY), 10)
      }
    },
    endMove(e) {

    },
    moving(e) {

    },
    /**
     * 计算当前item的位置和大小
     *
     * @param {any} item
     * @returns
     */
    nowItemStyle(item, index) {
      return {
        width: (this.cellWidth * (item.sizex) - this.baseMarginLeft) + 'px',
        height: (this.cellHeight * (item.sizey) - this.baseMarginTop) + 'px',
        left: (this.cellWidth * (item.x - 1) + this.baseMarginLeft) + 'px',
        top: (this.cellHeight * (item.y - 1) + this.baseMarginTop) + 'px'
      }
    },
    getList() {
      // 不使用copy 保持原有对象
      const finalList = []
      const _this = this
      _.forEach(this.componentData, function(item, index) {
        if (_.isEmpty(item)) return
        if (_this.canvasId === item.canvasId) {
          delete item['_dragId']
          delete item['show']
          if (item['auxiliaryMatrix']) {
            finalList.push(item)
          }
        }
      })
      return finalList
    },
    /**
     * 获取x最大值
     *
     * @returns
     */
    getMaxCell() {
      return this.maxCell
    },
    /**
     * 获取渲染状态
     *
     * @returns
     */
    getRenderState() {
      return this.moveAnimate
    },
    addItem: addItem,
    removeItem: removeItem,
    initMatrix: init,
    afterInitOk(func) {
      const timeid = setInterval(() => {
        if (this.moveAnimate) {
          clearInterval(timeid)
          func()
        }
      }, 100)
    },
    addItemBox(item) {
      this.yourList.push(item)

      this.$nextTick(function() {
        addItem.call(this, item, this.yourList.length - 1)
      })
    },
    removeLastItem() {
      if (this.canvasStyleData.auxiliaryMatrix) {
        this.removeItem(this.yourList.length - 1)
      }
    },
    startMoveIn() {
      if (this.$store.state.dragComponentInfo.auxiliaryMatrix && this.canvasId === 'canvas-main') {
        const moveInItemInfo = this.$store.state.dragComponentInfo
        this.addItemBox(moveInItemInfo)
        // e.preventDefault();
        if (!this.infoBox) {
          this.infoBox = {}
        }
        const infoBox = this.infoBox

        infoBox.moveItem = moveInItemInfo
        infoBox.moveItemIndex = this.yourList.length - 1

        infoBox.oldX = 1 // 实际对象原始X位置
        infoBox.oldY = 1
        infoBox.oldSizeX = moveInItemInfo.sizex
        infoBox.oldSizeY = moveInItemInfo.sizey
      }
    },
    // 调整父级组件边界
    resizeParentBoundsRef() {
      const _this = this
      _this.componentData.forEach(function(data, index) {
        _this.$refs.deDragRef && _this.$refs.deDragRef[index] && _this.$refs.deDragRef[index].checkParentSize()
      })
    },
    canvasDragging(mY, offsetY) {
      this.$emit('canvasDragging', mY, offsetY)
    }
  }
}
</script>

<style lang="scss" scoped>
.editor {
  width: 100%;
  position: relative;
  /*background: #fff;*/
  margin: auto;
  /*会影响设置组件不能出现在最高层*/
  /*overflow-x: hidden;*/
  background-size: 100% 100% !important;
  /*transform-style:preserve-3d;*/
  .lock {
    opacity: .5;
  }
}

.parent_transform {
  //transform transform 会使z-index 失效；为了使编辑仪表板时 按钮一直在上面 采用transform-style 的方式
  // transform-style 会导致 dialog 遮罩有问题 此处暂时用这个样式做控制
  transform-style: preserve-3d;
}

.edit {
  .component {
    outline: none;
    width: 100%;
    height: 100%;
    position: relative;
  }
}

.gap_class {
  padding: 3px;
}

.ref-line {
  position: absolute;
  background-color: #70c0ff;;
  z-index: 9999;
}

.v-line {
  width: 1px;
}

.h-line {
  height: 1px;
}

.dialog-css ::v-deep .el-dialog__title {
  font-size: 14px;
}

.dialog-css ::v-deep .el-dialog__header {
  padding: 40px 20px 0;
}

.dialog-css ::v-deep .el-dialog__body {
  padding: 10px 20px 20px;
}

</style>
